package wo.jpa.psys.generator;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Entity;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import wo.common.util.WoClassUtil;
import wo.common.util.WoUtil;
import wo.common.util.WoVelocityUtil;
import wo.jpa.reader.entity.WoJPAEntity;

/**
 * @author cailei
 * @date Nov 3, 2018
 */
public class PSysGenerator {

	private final static Logger LOG = LogManager.getLogger(PSysGenerator.class);

	/**
	 * @param rootDir
	 * @param entityClass
	 */
	public static void createCode(String rootDir, String entityClass) {
		LOG.info("createCode:rootDir-" + rootDir + ",entityClass-" + entityClass);
		// 构造实体数据
		WoJPAEntity e = new WoJPAEntity(entityClass);
		// 创建*Dto类
		createCode(rootDir, e, "dto", true);
		// 创建*Repository接口
		createCode(rootDir, e, "repository", false);
		// 创建*Service接口
		createCode(rootDir, e, "service", false);
		// 创建*ServiceImpl类
		createCode(rootDir, e, "service.impl", false);
		// 创建*Controller类
		createCode(rootDir, e, "controller", false);
	}

	/**
	 * @param rootDir
	 * @param entityClass
	 * @param module
	 */
	public static void createHtml(String rootDir, String entityClass) {
		LOG.info("createHtml:rootDir-" + rootDir + ",entityClass-" + entityClass);
		// 构造实体数据
		WoJPAEntity e = new WoJPAEntity(entityClass);
		rootDir = WoUtil.getDirEndWithFileSeparator(rootDir);
		// 创建文件所在目录
		String fileDir = rootDir + "templates/" + e.getModule() + "/";
		File dir = new File(fileDir);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		// 构造velocity数据
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("entity", e);
		// 设置文件路径
		String filePath = fileDir + e.getEntityNameLowerFirstChar() + ".html";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile("entity.html", filePath, map);
		// 设置文件路径
		filePath = fileDir + e.getEntityNameLowerFirstChar() + "-list.html";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile("entity-list.html", filePath, map);
		// 设置文件路径
		filePath = fileDir + e.getEntityNameLowerFirstChar() + "-selector.html";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile("entity-selector.html", filePath, map);
		// 设置文件路径
		filePath = fileDir + e.getEntityNameLowerFirstChar() + "-selector-list.html";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile("entity-selector-list.html", filePath, map);
		// 设置文件路径
		filePath = fileDir + e.getEntityNameLowerFirstChar() + "-create.html";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile("entity-create.html", filePath, map);
		// 设置文件路径
		filePath = fileDir + e.getEntityNameLowerFirstChar() + "-update.html";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile("entity-update.html", filePath, map);

		fileDir = rootDir + "static/js/" + e.getModule() + "/";
		dir = new File(fileDir);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		// 设置js文件路径
		filePath = fileDir + e.getEntityNameLowerFirstChar() + ".js";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile("entity.js", filePath, map);
		// 设置js文件路径
		filePath = fileDir + e.getEntityNameLowerFirstChar() + "Selector.js";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile("entitySelector.js", filePath, map);
		LOG.info("createHtml:" + entityClass + " OK.");
	}

	/**
	 * @param pkgName service.impl
	 * @return ServiceImpl
	 */
	private static String getClassSuffix(String pkgName) {
		String[] pkgs = pkgName.split("[.]");
		StringBuffer sb = new StringBuffer();
		for (String pkg : pkgs) {
			sb.append(WoUtil.getUpperFirstChar(pkg));
		}
		return sb.toString();
	}

	/**
	 * @param rootDir
	 * @param entityClass
	 */
	public static void createCode(String rootDir, WoJPAEntity e, String pkgName, Boolean hasParent) {
		rootDir = WoUtil.getDirEndWithFileSeparator(rootDir);
		LOG.info("createCode:" + pkgName + "...");
		// 创建文件所在目录
		String fileDir = rootDir + e.getSiblingPackage(pkgName).replace(".", "/") + "/";
		File dir = new File(fileDir);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		// 构造velocity数据
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("entity", e);
		// 设置文件路径
		String filePath = fileDir + e.getEntityName() + getClassSuffix(pkgName) + ".java";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile(pkgName + ".java", filePath, map);
		if (hasParent) {
			// 设置文件路径
			filePath = fileDir + e.getEntityName() + getClassSuffix(pkgName) + "_" + ".java";
			// 根据模板生成文件
			WoVelocityUtil.mergeToFile(pkgName + "_.java", filePath, map);
		}
		LOG.info("createCode:" + pkgName + " OK.");
	}

	/**
	 * 扫描pkgToScan包下所有@Entity注解的实体类,并为其在rootDir目录下生成DTO类的Java源代码.
	 * 
	 * @param rootDir
	 * @param pkgToScan
	 */
	public static void createCodeByPackage(String rootDir, String pkgToScan) {
		List<Class> classes = WoClassUtil.findClassesByPackage("./", pkgToScan);
		// 这个时候我们已经得到了指定包下所有的类的绝对路径了。我们现在利用这些绝对路径和java的反射机制得到他们的类对象
		for (Class s : classes) {
			if (s.getDeclaredAnnotation(Entity.class) != null) {
				createCode(rootDir, s.getName());
			}
		}
	}

	/**
	 * 扫描pkgToScan包下所有@Entity注解的实体类，并为其在rootDir目录下生成DTO类的HTML和js代码.
	 * 
	 * @param rootDir
	 * @param pkgToScan
	 */
	public static void createHtmlByPackage(String rootDir, String pkgToScan) {
		List<Class> classes = WoClassUtil.findClassesByPackage("./", pkgToScan);
		// 这个时候我们已经得到了指定包下所有的类的绝对路径了。我们现在利用这些绝对路径和java的反射机制得到他们的类对象
		for (Class s : classes) {
			if (s.getDeclaredAnnotation(Entity.class) != null) {
				createHtml(rootDir, s.getName());
			}
		}
	}

	public static void main(String[] args) {

	}

}
